#pragma once

#include "Util.hpp"

#include <string>
#include <vector>
#include <sstream>
#include <unordered_map>

const static string SEP = "\r\n";
const static string webRoot = "./webRoot";
const static string defaultHomePage = "/index.html"; // 默认页面
const static string errPage_404 = "/err404.html";    // 404页面

class Request
{
public:
    Request()
    {
    }

    // 反序列化
    bool Deserialization(const std::string &url)
    {
        // 根据 url 进行解析
        int n = 0;
        std::vector<std::string> vstr;
        while (true)
        {
            std::string line;
            n = Util::ReadLine(url, n, SEP, &line) + SEP.size();

            if (line.empty())
                break;

            vstr.push_back(line);
        }

        // 解析请求行
        ParseFirstLine(vstr[0]);

        // 解析报头部分
        ParseHeaderLine(vstr);

        // 读取并解析有效载荷（可能没有）
        Util::ReadLine(url, n, SEP, &_body);

        return true;
    }

    // 解析请求行
    bool ParseFirstLine(const std::string &str)
    {
        // 读取方法、资源路径、协议版本
        std::stringstream ss(str);
        ss >> _method >> _path >> _version;

        // 解析出后缀
        if (_path == "/")
            _path = defaultHomePage;

        // 实际路径 = web根目录 + 请求资源路径
        int pos = _path.find_last_of(".");
        if (pos == std::string::npos)
            _suffix = ".html";
        else
            _suffix = _path.substr(pos);
        _path = webRoot + _path;

        return true;
    }

    // 解析报头部分
    bool ParseHeaderLine(const std::vector<std::string> &vstr)
    {
        for (int i = 1; i < vstr.size(); i++)
        {
            const std::string &str = vstr[i];

            int pos = str.find(':');
            std::string key = str.substr(0, pos);
            std::string value = str.substr(pos + 2);

            _headers[key] = value;
        }

        return true;
    }

    ~Request()
    {
    }

public:
    std::string _method;                                   // 请求方法
    std::string _path;                                     // 资源路径
    std::string _suffix;                                   // 资源后缀
    std::string _version;                                  // 协议版本
    std::unordered_map<std::string, std::string> _headers; // 请求报头
    std::string _body;                                     // 有效载荷
};

class Response
{
public:
    Response()
    {
    }

    // 根据请求对象，构建出相应对象
    bool LoadInfo(const Request &req)
    {
        _version = req._version;

        // 读取资源
        std::string path = req._path;
        if (Util::ReadFile(path, &_body) == false)
        {
            _st_code = "404";
            _st_msg = "No Found";
            path = webRoot + errPage_404;
            Util::ReadFile(path, &_body);
        }
        else
        {
            _st_code = "200";
            _st_msg = "Ok";
        }

        std::cout << "path: " << path << std::endl;

        // 设置报头
        _headers["Content-Length"] = std::to_string(_body.size());
        _headers["Content-Type"] = Util::GetSuffix(req._suffix);

        return true;
    }

    // 序列化
    bool Serialization(std::string *outStr)
    {
        outStr->clear();

        *outStr = _version + " " + _st_code + " " + _st_msg + SEP;

        for (auto &kv : _headers)
        {
            *outStr += kv.first + ": " + kv.second + SEP;
        }
        *outStr += SEP;
        *outStr += _body;
        return true;
    }

    ~Response()
    {
        _headers.clear();
    }

public:
    std::string _version;                                  // 协议版本
    std::string _st_code;                                  // 状态码
    std::string _st_msg;                                   // 状态码信息
    std::unordered_map<std::string, std::string> _headers; // 响应报头
    std::string _body;                                     // 有效载荷
};